﻿using Dapper;
using DevExpress.Xpo;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MySqlConnector;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using YAKEJI.Abp.Database;
using YAKEJI.Abp.Domain.Repositories;
using YAPACS.BusinessObjects.Managements.Devices;
using YAPACS.BusinessObjects.Managements.Exams;
using YAPACS.BusinessObjects.Managements.Workflows;
using YAPACS.Organizations;
using YAPACS.RisServer.Services.Dtos;
using YAPACS.RisServer.Workflows.Statistic;
using YAPACS.Workflows;

namespace YAPACS.RisServer.Controllers;

[Authorize]
public class StatisticController : AbpControllerBase
{
    private readonly IRepository<ExamStatistics, Guid> _examStatisticsRepository;
    private readonly IRepository<Workflow, Guid> _workflowRepository;
    private readonly IGetAdvancedSearchView _getAdvancedSearchView;
    private readonly IAdvancedSearchExpression _advancedSearchExpression;
    private readonly ICurrentUserOrganization _currentUserOrganization;
    private readonly IWorkflowInvoker _invoker;
    private readonly IDatabaseConnectionProvider _databaseConnectionProvider;
    private readonly IConfiguration _configuration;
    private readonly IRepository<Department, Guid> _departmentRepository;

    public StatisticController(IRepository<ExamStatistics, Guid> examStatisticsRepository,
        IGetAdvancedSearchView getAdvancedSearchView,
        ICurrentUserOrganization currentUserOrganization,
        IAdvancedSearchExpression advancedSearchExpression,
        IRepository<Workflow, Guid> workflowRepository,
        IDatabaseConnectionProvider databaseConnectionProvider,
        IWorkflowInvoker invoker,
        IConfiguration configuration,
        IRepository<Department, Guid> departmentRepository)
    {
        _examStatisticsRepository = examStatisticsRepository;
        _getAdvancedSearchView = getAdvancedSearchView;
        _currentUserOrganization = currentUserOrganization;
        _advancedSearchExpression = advancedSearchExpression;
        _workflowRepository = workflowRepository;
        _databaseConnectionProvider = databaseConnectionProvider;
        _invoker = invoker;
        _configuration = configuration;
        _departmentRepository = departmentRepository;
    }
    [HttpGet("/api/exam-statistics/get-statistics")]
    public async Task<IActionResult> GetExamStatistics()
    {
        var result = new List<object>();
        var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
        var deviceTypes = department.GetDeviceTypes();
        if (deviceTypes.Count > 1)
        {
            result.Add(new
            {
                Id = department.Oid,
                Text = department.Name,
                IsDirectory = true,
                Selected = false,
                Expanded = true
            });
        }
        var statistics = await _examStatisticsRepository.GetListAsync(e => e.IsActive && e.Department.Oid == _currentUserOrganization.DepartmentId);
        result.AddRange(statistics.Where(x => x.DeviceType == null).OrderBy(e=>e.Order).Select(e => new
        {
            Id = e.Oid,
            Text = e.Name,
            ParentId = deviceTypes.Count > 1 ? e.Department?.Oid : null,
            IsDirectory = false,
            Selected = false,
            Expanded = true
        }));
        if (deviceTypes.Count > 1)
        {
            result.AddRange(deviceTypes.Select(e => new
            {
                Id = e.Oid,
                Text = e.Name,
                ParentId = department.Oid,
                IsDirectory = true,
                Selected = false,
                Expanded = true
            }));
        }
        result.AddRange(statistics.Where(x => x.DeviceType != null).OrderBy(e => e.Order).Select(e => new
        {
            Id = e.Oid,
            Text = e.Name,
            ParentId = deviceTypes.Count > 1 ? e.DeviceType?.Oid : null,
            IsDirectory = false,
            Selected = false,
            Expanded = true
        }));
        return Ok(new WorkflowOutput { Success = true, Data = result });
    }
    /// <summary>
    /// 获取高级搜索视图
    /// </summary>
    /// <returns></returns>
    [HttpPost("api/exam-statistics/get-advanced-search-view")]
    public async Task<IActionResult> GetExamStatisticsAdvancedSearchView([FromBody] WorkflowInput input)
    {
        try
        {
            if (!input.ContainsKey("filterId"))
            {
                throw new Exception("未找到统计Id");
            }
            if (input.Count == 1)
            {
                var filterId = Guid.Parse(input.GetValueOrDefault("filterId")?.ToString());
                var examStatistics = await _examStatisticsRepository.GetAsync(filterId);
                var result = await _getAdvancedSearchView.InvokeAsync(new WorkflowInput { { "ExamStatistics", examStatistics } });
                result.NextApi = "/api/exam-statistics/get-advanced-search-view";
                return Ok(result);
            }
            else
            {
                return Ok(new WorkflowOutput { Success = true, Data = input, Info = "null" });
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await UnitOfWorkManager.Current.RollbackAsync();
            return Ok(new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            });
        }
    }
    [UnitOfWork]
    [HttpPost("api/exam-statistics/get-list")]
    public async Task<IActionResult> GetList([FromBody] DataGridRequest request)
    {
        try
        {
            using var uow = UnitOfWorkManager.Begin(true, true);
            if (request.UserData.Count == 0)
            {
                return Ok(new WorkflowOutput { Success = true });
            }
            else
            {
                var input = new WorkflowInput();
                List<Column> columns = [];
                List<dynamic> rows = [];
                var filterId = Guid.Parse(request.UserData.GetValueOrDefault("filterId")?.ToString());
                var examStatistics = await _examStatisticsRepository.GetAsync(filterId);
                request.UserData.Add("deviceTypeId", examStatistics.DeviceType?.Oid);
                request.UserData.Add("departmentId", examStatistics.Department.Oid);
                foreach (var item in request.UserData)
                {
                    input.Add(item.Key, item.Value);
                }
                if (!string.IsNullOrWhiteSpace(examStatistics.SQL))
                {
                    var workflowOutput = await _advancedSearchExpression.InvokeAsync(input);
                    if (!workflowOutput.Success)
                    {
                        throw new Exception(workflowOutput.Error);
                    }
                    var obs = await _examStatisticsRepository.GetObjectSpaceAsync();
                    using var connection = _databaseConnectionProvider.GetDbConnection(obs.Connection switch
                    {
                        MySqlConnection => obs.Connection.ConnectionString,
                        _ => _configuration.GetConnectionString("Default")
                    }, obs.Connection switch
                    {
                        MySqlConnection => DatabaseType.MySql,
                        _ => DatabaseType.SqlServer
                    });
                    rows = (await connection.QueryAsync(examStatistics.SQL, workflowOutput.Data)).ToList();
                    foreach (var row in rows)
                    {
                        foreach (var property in (IDictionary<string, object>)row)
                        {
                            columns.Add(new Column { DataField = property.Key, Caption = property.Key });
                        }
                        break;
                    }
                }
                if (!string.IsNullOrWhiteSpace(examStatistics.WorkflowCode))
                {
                    input.Add("Rows", rows);
                    input.Add("Columns", columns);
                    var workflow1 = await _workflowRepository.GetAsync(e => e.Code == examStatistics.WorkflowCode);

                    var workflowOutput = await _invoker.InvokeByCodeAsync(examStatistics.WorkflowCode, input);
                    return Ok(workflowOutput);
                }
                else
                {
                    return Ok(new WorkflowOutput
                    {
                        Success = true,
                        Data = new
                        {
                            Columns = columns,
                            Rows = rows,
                            TotalCount = rows.Count
                        }
                    });
                }
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            return Ok(new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            });
        }
    }
}
